package com.yourenbang.lingyun.transaction.web.service.impl.fund;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.yourenbang.lingyun.constants.BizCodeMessages;
import com.yourenbang.lingyun.constants.Constant;
import com.yourenbang.lingyun.constants.enums.ChannelIdEnums;
import com.yourenbang.lingyun.constants.enums.PlatNoEnums;
import com.yourenbang.lingyun.constants.enums.fund.AccountType;
import com.yourenbang.lingyun.core.config.datasource.DataSources;
import com.yourenbang.lingyun.core.config.datasource.RoutingDataSource;
import com.yourenbang.lingyun.core.message.Result;
import com.yourenbang.lingyun.core.util.KLog;
import com.yourenbang.lingyun.domain.*;
import com.yourenbang.lingyun.mapper.AllyMapper;
import com.yourenbang.lingyun.mapper.FundAccountMapper;
import com.yourenbang.lingyun.mapper.UserBaseMapper;
import com.yourenbang.lingyun.transaction.mapper.TransactionFundAccountMapper;
import com.yourenbang.lingyun.transaction.web.domain.po.TsFundAccount;
import com.yourenbang.lingyun.transaction.web.service.fund.FundService;
import com.yourenbang.transaction.api.model.dto.fund.*;
import com.yourenbang.transaction.api.model.vo.fund.FundQueryVO;
import com.yourenbang.transaction.api.service.fund.FundApiService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@RestController
public class FundApiServiceImpl implements FundApiService {

    @Autowired
    private FundAccountMapper fundAccountMapper;
    @Autowired
    private TransactionFundAccountMapper transactionFundAccountMapper;
    @Autowired
    private UserBaseMapper userBaseMapper;
    @Autowired
    private AllyMapper allyMapper;

    private static final String ACTIVE_EARNING = "激活返现";
    private static final String REACH_EARNING = "达标奖励";
    private static final String PUSH_EARNING = "推卡奖励";
    private static final String PROFIT_EARNING = "分润收益";
    private static final String BEAN_EARNING = "活跃度奖励";
    //所有时间
    private static final String TOTAL = "total";
    @Autowired
    private FundService fundService;

    /**
     * 查询用户所有账户
     */
    @RoutingDataSource(DataSources.SLAVE_DB)
    @Override
    public Result<Map<Integer, FundQueryVO>> queryAllFund(FundQueryDTO fundQueryDTO) {

        KLog.info("[查询用户所有账户]入参:{}", fundQueryDTO.toJSON());
        Map<Integer, FundQueryVO> resMap = new HashMap<>();
        FundAccountExample fundAccountExample = new FundAccountExample();
        fundAccountExample.createCriteria()
                .andUserBaseIdEqualTo(fundQueryDTO.getUserBaseId())
                .andAccountStatusEqualTo(TsFundAccount.ACCOUNT_STATUS_ON);
        List<FundAccount> fundAccountList = fundAccountMapper.selectByExample(fundAccountExample);
        if (CollectionUtils.isEmpty(fundAccountList)) {
            return Result.builder().success(resMap);
        }
        for (FundAccount fundAccount : fundAccountList) {
            FundQueryVO fundQueryVO = new FundQueryVO();
            fundQueryVO.setAccountWithdrawable(fundAccount.getAccountAmountWithdrawable());
            fundQueryVO.setAccountWithdrawed(fundAccount.getAccountAmountWithdrawed());
            fundQueryVO.setAccountFrozen(fundAccount.getAccountAmountFrozen());
            fundQueryVO.setAccountIncome(fundAccount.getAccountIncome());
            resMap.put(fundAccount.getAccountType(), fundQueryVO);
        }
        KLog.info("[查询用户所有账户]出参:{}, 入参:{}", resMap, fundQueryDTO.toJSON());
        return Result.builder().success(resMap);

    }

    /**
     * 查询用户指定账户
     */
    @Override
    public Result<FundQueryVO> queryOneFund(FundQueryOneDTO fundQueryOneDTO) {
        FundAccountExample fundAccountExample = new FundAccountExample();
        fundAccountExample.createCriteria()
                .andUserBaseIdEqualTo(fundQueryOneDTO.getUserBaseId())
                .andAccountTypeEqualTo(fundQueryOneDTO.getAccountType())
                .andAccountStatusEqualTo(TsFundAccount.ACCOUNT_STATUS_ON);
        List<FundAccount> fundAccountList = fundAccountMapper.selectByExample(fundAccountExample);
        if (CollectionUtils.isEmpty(fundAccountList)) {
            return Result.builder().fail(BizCodeMessages.TRANSACTION_ACCOUNT_NONE);
        }
        FundAccount fundAccount = fundAccountList.get(0);
        FundQueryVO fundQueryVO = new FundQueryVO();
        fundQueryVO.setAccountWithdrawable(fundAccount.getAccountAmountWithdrawable());
        fundQueryVO.setAccountWithdrawed(fundAccount.getAccountAmountWithdrawed());
        fundQueryVO.setAccountFrozen(fundAccount.getAccountAmountFrozen());
        return Result.builder().success(fundQueryVO);
    }

    /**
     * 查询盟友的各项收入
     *
     * @param dto
     * @return
     */
    @Override
    public Result<List<MonthEarningDataVO>> queryUserAccountDetail(QueryUserAccountDetailDTO dto) {
        log.info("查询盟友的各项收入,dto={}", JSON.toJSON(dto));
        //用户信息校验
        if (!checkUser(dto.getUserBaseId())) {
            return Result.builder().fail(BizCodeMessages.PARAMETER_ERR, "用户不是盟友");
        }

        List<MonthEarningDataVO> result = new ArrayList<>();

        //定义资金账户类型集合
        List<String> fundList = Arrays.asList(
                String.format("%s%s", PlatNoEnums.YXY.getCode(), AccountType.ALLY.getShortAccountNo()),
                String.format("%s%s", PlatNoEnums.YXY.getCode(), AccountType.ALLY_REACH.getShortAccountNo()),
                String.format("%s%s", PlatNoEnums.YXY.getCode(), AccountType.CREDIT_COMMISSION.getShortAccountNo()),
                String.format("%s%s", PlatNoEnums.YXY.getCode(), AccountType.ALLY_PROFIT.getShortAccountNo()),
                String.format("%s%s", PlatNoEnums.YXY.getCode(), AccountType.SUB_TEAM_ACTION.getShortAccountNo())
        );

        //查询用户全部收入
        if (dto.getQueryType().equals(QueryUserAccountDetailDTO.QUERY_TYPE_10)) {
            List<EarningDataVO> amountDataVOS = new ArrayList<>();
            MonthEarningDataVO monthEarningDataVO = new MonthEarningDataVO();
            //查询各种类型收入x
            List<AccountTypeEarningVO> fundAccounts
                    = transactionFundAccountMapper.findFundAccountByType(fundList, dto.getUserBaseId());
            //按类型赋值
            for (AccountTypeEarningVO fundAccount : fundAccounts) {
                //如果账户类型为盟友类型，则减去充值金额
                if (fundAccount.getAccountType().equals(String.format("%s%s", PlatNoEnums.YXY.getCode(), AccountType.ALLY.getShortAccountNo()))) {
                    BigDecimal recharge = transactionFundAccountMapper
                            .findRechargeByType(dto.getUserBaseId(), fundAccount.getAccountType());
                    if (Objects.nonNull(recharge) && recharge.compareTo(BigDecimal.ZERO) > 0) {
                        fundAccount.setEarning(fundAccount.getEarning().subtract(recharge));
                    }
                }
                EarningDataVO amountDataVO = new EarningDataVO();
                amountDataVO.setAccountType(fundAccount.getAccountType());
                amountDataVO.setEarning(fundAccount.getEarning());
                amountDataVO.setShowName(getEarningName(fundAccount.getAccountType()));
                amountDataVOS.add(amountDataVO);
                monthEarningDataVO.setMonth(TOTAL);
                monthEarningDataVO.setEarningDataVOS(amountDataVOS);
            }
            result.add(monthEarningDataVO);
        } else if (dto.getQueryType().equals(QueryUserAccountDetailDTO.QUERY_TYPE_20)) {
            //按月查询各类收入
            dto.getMonths().forEach(month -> {
                List<EarningDataVO> amountDataVOS = new ArrayList<>();
                String day = month + "01";
                MonthEarningDataVO monthEarningDataVO = new MonthEarningDataVO();
                List<AccountTypeEarningVO> monthFundAccounts
                        = transactionFundAccountMapper.findMonthFundAccountByType(fundList, dto.getUserBaseId(), day);
                //按类型赋值
                for (AccountTypeEarningVO fundAccount : monthFundAccounts) {
                    EarningDataVO amountDataVO = new EarningDataVO();
                    amountDataVO.setAccountType(fundAccount.getAccountType());
                    amountDataVO.setEarning(fundAccount.getEarning());
                    amountDataVO.setShowName(getEarningName(fundAccount.getAccountType()));
                    amountDataVOS.add(amountDataVO);
                }
                monthEarningDataVO.setMonth(month);
                monthEarningDataVO.setEarningDataVOS(amountDataVOS);
                result.add(monthEarningDataVO);
            });
        }
        log.info("查询盟友的各项收入结果,result={}", JSON.toJSON(result));
        return Result.builder().success(result);
    }

    /**
     * 为指定userbaseID创建资金账号
     *
     * @param fundAddParamsDTO
     * @return
     */
    @Override
    public Result<List<FundAccount>> bossAccountAddIfNotExist(FundAddParamsDTO fundAddParamsDTO) {

        List<FundAccount> fundAccountList = new ArrayList<>();
        fundAccountList.add(createFundAccountIfNotExist(fundAddParamsDTO, AccountType.SYS_BOSS_OUT));
        fundAccountList.add(createFundAccountIfNotExist(fundAddParamsDTO, AccountType.SYS_BOSS_WITHDRAW));

        return Result.builder().success(fundAccountList);
    }

    @Override
    public Result<List<FundAccount>> allyAccountAddIfNotExist(FundAddParamsDTO fundAddParamsDTO) {

        List<FundAccount> fundAccountList = new ArrayList<>();
        fundAccountList.add(createFundAccountIfNotExist(fundAddParamsDTO, AccountType.ALLY_V2));
        fundAccountList.add(createFundAccountIfNotExist(fundAddParamsDTO, AccountType.ALLY_FROM_BOSS));

        return Result.builder().success(fundAccountList);
    }

    @Override
    public Result<List<FundAccount>> merchantAccountAddIfNotExist(FundAddParamsDTO fundAddParamsDTO) {

        List<FundAccount> fundAccountList = new ArrayList<>();
        fundAccountList.add(createFundAccountIfNotExist(fundAddParamsDTO, AccountType.MER));
        fundAccountList.add(createFundAccountIfNotExist(fundAddParamsDTO, AccountType.MERCHANT_FROM_BOSS));

        return Result.builder().success(fundAccountList);
    }

    /**
     * 取消资金变动计划
     *
     * @param orderNo 订单号
     * @return
     */
    @Override
    public Result cancelByOrderNo(String orderNo) {
        return fundService.cancelByOrderNo(orderNo);
    }

    /**
     * 通过账户类型得到收入类型名字
     *
     * @param fullAccountType
     * @return
     */
    private String getEarningName(String fullAccountType) {
        Integer iFullAccountType = Integer.parseInt(fullAccountType);

        if (AccountType.ALLY.isEqualsFullAccountNo(iFullAccountType)) {
            return ACTIVE_EARNING;
        } else if (AccountType.ALLY_REACH.isEqualsFullAccountNo(iFullAccountType)) {
            return REACH_EARNING;
        } else if (AccountType.CREDIT_COMMISSION.isEqualsFullAccountNo(iFullAccountType)) {
            return PUSH_EARNING;
        } else if (AccountType.ALLY_PROFIT.isEqualsFullAccountNo(iFullAccountType)) {
            return PROFIT_EARNING;
        } else if (AccountType.SUB_TEAM_ACTION.isEqualsFullAccountNo(iFullAccountType)) {
            return BEAN_EARNING;
        }
        return "";
    }

    /**
     * 用户信息校验
     *
     * @return
     */
    private boolean checkUser(String userBaseId) {
        //是否存在
        UserBase userBase = userBaseMapper.selectByPrimaryKey(userBaseId);
        if (ObjectUtil.isEmpty(userBase)) {
            return false;
        }

        //是否为盟友
        AllyExample allyExample = new AllyExample();
        allyExample.createCriteria().andUserBaseIdEqualTo(userBaseId);
        List<Ally> allies = allyMapper.selectByExample(allyExample);
        if (CollectionUtils.isEmpty(allies)
                || allies.get(0).getAllyFlag().equals(Constant.NO)) {
            return false;
        }

        return true;

    }

    private FundAccount createFundAccountIfNotExist(FundAddParamsDTO fundAddParamsDTO, AccountType accountType) {

        UserBase userBase = userBaseMapper.selectByPrimaryKey(fundAddParamsDTO.getUserBaseId());
        LocalDateTime now = LocalDateTime.now();

        FundAccount fundAccount = new FundAccount();
        fundAccount.setAccountName(userBase.getUserName());
        fundAccount.setUserBaseId(fundAddParamsDTO.getUserBaseId());
        fundAccount.setChannelId(ChannelIdEnums.no.getCode());
        fundAccount.setAccountStatus(TsFundAccount.ACCOUNT_STATUS_ON);
        fundAccount.setAccountIncome(BigDecimal.ZERO);
        fundAccount.setAccountAmountFrozen(BigDecimal.ZERO);
        fundAccount.setAccountAmountWithdrawable(BigDecimal.ZERO);
        fundAccount.setAccountAmountWithdrawed(BigDecimal.ZERO);
        fundAccount.setAccountAmountUndepositable(BigDecimal.ZERO);
        fundAccount.setUpdateTime(now);
        fundAccount.setCreateTime(now);
        fundAccount.setPlatNo(fundAddParamsDTO.getPlatNo());
        fundAccount.setIsDel(Constant.NORMAL);


        Integer fullAccountType = accountType.getFullCode(fundAddParamsDTO.getPlatNo());
        FundAccountExample fundAccountExample = new FundAccountExample();
        fundAccountExample.createCriteria()
                .andUserBaseIdEqualTo(fundAddParamsDTO.getUserBaseId())
                .andAccountTypeEqualTo(fullAccountType)
                .andPlatNoEqualTo(fundAddParamsDTO.getPlatNo());
        List<FundAccount> fundAccounts = fundAccountMapper.selectByExample(fundAccountExample);

        //如果不存在,则创建
        if (fundAccounts.isEmpty()) {
            fundAccount.setAccountType(fullAccountType);
            fundAccount.setAccountTypeName(accountType.getAccountName());
            //创建支出账户
            fundAccountMapper.insert(fundAccount);
        }

        return fundAccount;
    }

}
